/*
 This program is submitted as part of an assignment in the
 J2E
 Fall Semester 2010-2011 
 School of Computer Science
 Interdisciplinary Center, Hertzelia, Israel 

 http://www.idc.ac.il 

 Exercise No.         : 3
 File Name            : GameControllerProxy.java
 Names (First Last)   : Itay Sorani, Nadav Ziv, Yonathan Zarsky
 Student No.          : 066530254, 039937883, 039692918
 */

package com.example;

import java.io.DataInputStream;
import java.io.IOException;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.util.Log;

import com.example.communication.ResultMarshaller;
import com.example.communication.ResultMarshallerJson;

/**
 * Sends the request of init/move/create model to the server and unmarshal the response.
 * Holds the url that we add to it the methods. 
 */
public class GameControllerProxy {

    // Note: In a more complete application this url will be build according to settings
    private String baseUrl = "http://10.0.2.2:8080/game/controller?userAgent=mobile";

    // A listener to responses that corresponds to user requests
    private GameControllerListener listener;

    // A strategy for unmarshaling the results
    private ResultMarshaller marshaller;

    private HttpClient client;

    /**
     * Constructs a GameControllerProxy
     */
    public GameControllerProxy() {
        marshaller = new ResultMarshallerJson();
        client = new DefaultHttpClient();
    }

	/**
     * Registers a listener to responses for requests made via this proxy
     */
    public void setListener(GameControllerListener listener) {
        this.listener = listener;
    }

    /**
     * A request for loading the initial model of the game
     */
    public void loadIniticalModel() {
        Runnable task = new Runnable() {
            public void run() {
                try {
                    TaskResult result = sendRequest(baseUrl + "&method=init");
                    if (listener != null) {
                        listener.onResult(result);
                    }
                } catch (IOException e) {
                    notifyFailure("Failed to perform request due to communication problem");
                }
            }
        };
        new Thread(task).start();
    }

    /**
     * A request for moving a cell with a given value to its (presumably) adjacent cell
     */
    public void performNewModelCreationRequest(int xTouchPosition,int yTouchPosition) {
        final String url = baseUrl + "&method=newModelCreation" + "&xTouchPosition=" + xTouchPosition + "&yTouchPosition=" + yTouchPosition;
        Runnable task = new Runnable() {
            public void run() {
                try {
                    TaskResult result = sendRequest(url);
                    if (listener != null) {
                        listener.onResult(result);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    notifyFailure("Failed to perform request due to communication problem");
                }
            }
        };
        new Thread(task).start();
    }
    
    /**
     * A request for moving a cell with a given value to its (presumably) adjacent cell
     */
    public void performInit() {
        final String url = baseUrl + "&method=init";
        Runnable task = new Runnable() {
            public void run() {
                try {
                    TaskResult result = sendRequest(url);
                    if (listener != null) {
                        listener.onResult(result);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    notifyFailure("Failed to perform request due to communication problem");
                }
            }
        };
        new Thread(task).start();
    }
     
    /**
     * A request for moving a cell with a given value to its (presumably) adjacent cell
     */
    public void performGameExit() {
        final String url = baseUrl + "&method=gameExit" + "&GameExit";
        Runnable task = new Runnable() {
            public void run() {
                try {
                    TaskResult result = sendRequest(url);
                    if (listener != null) {
                        listener.onResult(result);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    notifyFailure("Failed to perform request due to communication problem");
                }
            }
        };
        new Thread(task).start();
    }

    // Notifies the listener (if one exists) about a failure in performing a certain request
    private void notifyFailure(String message) {
        TaskResult result = new TaskResult();
        result.setErrorMessage(message);
        if (listener != null) {
            listener.onResult(result);
        }
    }

    // Sends a given request (encoded as a url) to the server and returns the result.
    // Note: this method is synchronous - it blocks until the results is read or an error on the socket occurred
    private TaskResult sendRequest(String url) throws IOException {
    	HttpGet request = new HttpGet(url);
        Log.v("Msg:", "request is: " + url);
        HttpResponse response = null;
        try {
        	response = client.execute(request);
        	if (response.getStatusLine().getStatusCode() != 200) {
        		System.out.println("Failed to perform request");
        	}
        } catch (IOException e) {
			 System.out.println(e.getMessage());
		} catch (Exception e) {
			 System.out.println(e.getMessage());
		}
        if (response != null) {
        	DataInputStream input = new DataInputStream(response.getEntity().getContent());
        	return marshaller.unmarshal(input);
        }
        return (null);
    }
}

